home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK2.toast / Development Kits (Disc 2) / QuickTime Conferencing / Programming Stuff / Sample Code / SeeWorld / Rogues.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-23  |  13.4 KB  |  769 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Rogues.c
  3.  
  4.     Contains:    A Sample MovieTalk Conferencing Application
  5.  
  6.     Written by:    Guy Riddle
  7.  
  8.     Copyright:    © 1994 by Apple Computer, Inc., all rights reserved.
  9. */
  10.  
  11. #include <Types.h>
  12. #include <QuickDraw.h>
  13. #include <Fonts.h>
  14. #include <Events.h>
  15. #include <Windows.h>
  16. #include <Menus.h>
  17. #include <Dialogs.h>
  18. #include <Desk.h>
  19. #include <ToolUtils.h>
  20. #include <Memory.h>
  21. #include <SegLoad.h>
  22. #include <Files.h>
  23. #include <Folders.h>
  24. #include <OSUtils.h>
  25. #include <DiskInit.h>
  26. #include <Scrap.h>
  27.  
  28. #include <String.h>
  29. #include <Strings.h>
  30. #include <stdio.h>
  31.  
  32. #include <QuickTimeConferencing.h>
  33.  
  34. #include "See.h"
  35.  
  36. typedef    EventRecord            *EventRecordPtr;
  37. typedef    Byte                *BytePtr;
  38. typedef    Boolean                *BooleanPtr;
  39. typedef    void                *VoidPtr;
  40.  
  41. #define     TOPLEFT(rect)     (*((Point *)(&(rect))))
  42.  
  43. #define        PW_CLEAR        'pw-C'
  44.  
  45. #define        MAXMEMBERS        4
  46.  
  47. typedef struct {
  48.     Rect                    box;
  49.     MTConferenceMember        member;
  50.     MTControllerComponent    controller;
  51. } Member, *MemberPtr;
  52.  
  53. #define        WRECT(top, left)    (top),(left),(top+120),(left+160)
  54. #define        RBOX(n)                (20),((n)*100-80),(80),((n)*100)
  55.  
  56.     Member                    gMember[MAXMEMBERS+1]    = {
  57.                                 {    WRECT(100, 100)        },
  58.                                 {    RBOX(1)                },
  59.                                 {    RBOX(2)                },
  60.                                 {    RBOX(3)                },
  61.                                 {    RBOX(4)                },
  62.                             };
  63.                             
  64.     MTCString63                gUserName, gPassword;
  65.     
  66.     ComponentInstance        gCC, gBC;
  67.     MTConferenceToken        gConference;
  68.     
  69.     WindowPtr                gGallery;
  70.     MTControllerActionFilterUPP    gGetInOnTheActionUPP;
  71.     
  72.     MemberPtr        FindMember(MTConferenceMember);
  73.     MemberPtr        FindController(MTControllerComponent);
  74.  
  75.     void            Initialize(void);
  76.     void            StartMovieTalk(void);
  77.     void            StopMovieTalk(void);
  78.     void            EventLoop(void);
  79.     
  80.     void            DoToolboxEvent(EventRecordPtr);
  81.     void            DoKeyDownEvent(EventRecordPtr);
  82.     void            DoUpdateEvent(EventRecordPtr);
  83.     void            DoMouseDownEvent(EventRecordPtr);
  84.     void            DoDiskEvent(EventRecordPtr);
  85.     void            AdjustMenus(void);
  86.     void            DoMenuBar(long);
  87.     void            DoAppleMenu(short);
  88.     void            DoFileMenu(short);
  89.     void            DoVideoPhoneMenu(short);
  90.     void            DoMenuCall(void);
  91.     void            DoMenuHangUp(void);
  92.     
  93.     void            DoConferenceEvent(MTConferenceEventPtr);
  94.     void            DoConfReady(MTConferenceEventPtr);
  95.     void            DoMemberReady(MTConferenceEventPtr);
  96. pascal Boolean        GetInOnTheAction(MTControllerComponent, MTControllerActionType, VoidPtr, long);
  97.     void            DoMemberTerminated(MTConferenceEventPtr);
  98.     void            DoConfTerminated(MTConferenceEventPtr);
  99.     void            DoPhoneRinging(MTConferenceEventPtr);
  100.     Boolean            Requires(MTConferenceMember, OSType);
  101.     Handle            GetPassword(Ptr);
  102.     void            EnableButton(DialogRef, short, Boolean);
  103.     void            GetValue(BytePtr, DialogRef, short);
  104.     void            DoIncomingCall(MTConferenceEventPtr);
  105.     void            DoMemberJoining(MTConferenceEventPtr);
  106.  
  107.     void            CallOne(MTNamePtr);
  108.     void            Sorry(int, int, MTConferenceMember, OSErr);
  109.     
  110. /*
  111.  *    Rogues
  112.  *
  113.  *    Is a permutation of See that illustrates placing the incoming video into a user-managed
  114.  *    window.
  115.  *
  116.  *    • The controllers, though required, aren't visible
  117.  *
  118.  *    • The video is forced into a fixed-size area regardless of the size of the self view
  119.  *    window on the sender's machine
  120.  */
  121.  
  122. void main()
  123. {
  124.     Initialize();
  125.     EventLoop();
  126. }
  127.  
  128.     void 
  129. Initialize(
  130.     void
  131. ){
  132.     Handle                    menuBar;
  133.     DialogPtr                dp;
  134.  
  135.     InitGraf((Ptr) &qd.thePort);
  136.     InitFonts();
  137.     InitWindows();
  138.     InitMenus();
  139.     TEInit();
  140.     InitDialogs(nil);
  141.     InitCursor();
  142.  
  143.     dp = GetNewDialog(rAboutAlert, nil, (WindowRef) -1);
  144.     DrawDialog(dp);
  145.             
  146.     StartMovieTalk();
  147.     
  148.  
  149.     menuBar = GetNewMBar(rRoguesMenuBar);
  150.  
  151.     SetMenuBar(menuBar);
  152.     DisposHandle(menuBar);
  153.     AddResMenu(GetMHandle(mApple), 'DRVR');
  154.  
  155.     DrawMenuBar();
  156.     
  157.     DisposeDialog(dp);
  158. }
  159.  
  160.     void
  161. StartMovieTalk(
  162.     void
  163. ){
  164.     StringHandle            sh;
  165.  
  166.     sh = GetString(kMTAppleTalkUserName);
  167.     
  168.     strncpy((char*)gUserName, (char*)*sh+1, **sh);
  169.     
  170.     gCC = OpenDefaultComponent(kMTConferenceType, kMTMovieTalkSubType);
  171.     
  172.     gMember[0].controller = MTConferenceNewPreparedController(gCC, &gMember[0].box,
  173.                               mtMediaSourcePrepMask+mtGrabVideoPrepMask+mtGrabAudioPrepMask+mtWindowVisiblePrepMask+mtControllerVisiblePrepMask,
  174.                               (MTCString)"Chief Inspector");
  175.     
  176.     MTConferenceListen(gCC, gUserName, gUserName, (MTCString)"mtlkatlk\tVideoPhone\x0Dmtlktcpi\t458\x0Dmtlkisdn\t-\x0D");
  177.  
  178.     gGetInOnTheActionUPP = NewMTControllerActionFilterProc(GetInOnTheAction);
  179.     
  180.     MTConferenceSetDefaultActionFilter(gCC, gGetInOnTheActionUPP, 0);
  181.     
  182.     gGallery = GetNewCWindow(rRogueWindow, nil, nil);
  183.     
  184.     gBC = OpenDefaultComponent(kMTBrowserType, kMTAppleTalkSubType);
  185. }                            
  186.  
  187.     void
  188. EventLoop(
  189.     void
  190. ){
  191.     EventRecord                tEvent;
  192.     MTConferenceEvent        cEvent;
  193.  
  194.     for(;;){
  195.         if(MTConferenceGetNextEvent(gCC, &cEvent))
  196.             DoConferenceEvent(&cEvent);
  197.             
  198.         if(WaitNextEvent(everyEvent, &tEvent, 1, 0))
  199.             DoToolboxEvent(&tEvent);
  200.     }
  201. }
  202.  
  203.     void
  204. DoToolboxEvent(
  205.     EventRecordPtr            ev
  206. ){
  207.     switch(ev->what) {
  208.     case mouseDown:
  209.         DoMouseDownEvent(ev);
  210.         break;
  211.     
  212.     case keyDown:
  213.         DoKeyDownEvent(ev);
  214.         break;
  215.         
  216.     case updateEvt:
  217.         DoUpdateEvent(ev);
  218.         break;
  219.     
  220.     case diskEvt:
  221.         DoDiskEvent(ev);
  222.     }
  223. }
  224.  
  225.     void
  226. DoMouseDownEvent(
  227.     EventRecordPtr            ev
  228. ){
  229.     WindowPtr                wp;
  230.     short                    part;
  231.     Rect                    box;
  232.     
  233.     part = FindWindow(ev->where, &wp);
  234.     
  235.     switch(part){
  236.     case inMenuBar:
  237.         AdjustMenus();
  238.         DoMenuBar(MenuSelect(ev->where));
  239.         break;
  240.         
  241.     case inContent:
  242.         SelectWindow(wp);
  243.         break;
  244.         
  245.     case inDrag:
  246.         box = (*GetGrayRgn())->rgnBBox;
  247.         
  248.         DragWindow(wp, ev->where, &box);
  249.     }
  250. }
  251.  
  252.     void
  253. DoKeyDownEvent(
  254.     EventRecordPtr            ev
  255. ){
  256.     if(ev->modifiers & cmdKey){
  257.         AdjustMenus();    
  258.         DoMenuBar(MenuKey(ev->message & charCodeMask));
  259.     }
  260. }
  261.  
  262.     void
  263. DoUpdateEvent(
  264.     EventRecordPtr            ev
  265. ){
  266.     WindowPtr                wp;
  267.     int                        i;
  268.     
  269.     wp = (WindowPtr) ev->message;
  270.     SetPort(wp);
  271.     
  272.     TextFont(newYork);
  273.     TextSize(48);
  274.     
  275.     BeginUpdate(wp);
  276.     
  277.     for(i = 1; i <= MAXMEMBERS; i++){
  278.         TextBox("?", 1, &gMember[i].box, teJustCenter);
  279.         FrameRect(&gMember[i].box);
  280.     }
  281.     
  282.     EndUpdate(wp);
  283. }
  284.  
  285.     void
  286. DoDiskEvent(
  287.     EventRecordPtr            ev
  288. ){
  289.     Point                    where;
  290.  
  291.     if(HiWord(ev->message)){
  292.         SetPt(&where, kDILeft, kDITop);
  293.         DIBadMount(where, ev->message);
  294.     }
  295. }
  296.  
  297.     void
  298. AdjustMenus(
  299.     void
  300. ){
  301.     MenuHandle                mh;
  302.     
  303.     mh = GetMHandle(mVideoPhone);
  304.     
  305.     gConference ? EnableItem(mh, iHangUp) : DisableItem(mh, iHangUp);
  306.     FindMember(0) ? EnableItem(mh, iCall) : DisableItem(mh, iCall);
  307. }
  308.  
  309.     void
  310. DoMenuBar(
  311.     long                    selection
  312. ){
  313.     short                    menuID;    
  314.     short                    menuItem;
  315.  
  316.     menuID = HiWord(selection);
  317.     menuItem = LoWord(selection);
  318.     
  319.     switch(menuID){
  320.     case mApple:
  321.         DoAppleMenu(menuItem);
  322.         break;
  323.         
  324.     case mFile:
  325.         DoFileMenu(menuItem);
  326.         break;
  327.         
  328.     case mEdit:                    /* call SystemEdit for DA editing & MultiFinder */
  329.         SystemEdit(menuItem-1);
  330.         break;
  331.         
  332.     case mVideoPhone:
  333.         DoVideoPhoneMenu(menuItem);
  334.     }
  335.     
  336.     HiliteMenu(0);
  337. }
  338.  
  339.     void
  340. DoAppleMenu(
  341.     short                    item
  342. ){
  343.     DialogRef                dp;
  344.     Str255                    daName;
  345.     short                    itemHit;
  346.  
  347.     switch(item){
  348.     case iAbout:
  349.         dp = GetNewDialog(rAboutAlert, nil, (WindowRef) -1);
  350.         SetDialogDefaultItem(dp, 1);
  351.         
  352.         ModalDialog(0, &itemHit);
  353.         
  354.         DisposeDialog(dp);
  355.         break;
  356.         
  357.     default:            /* all non-About items in this menu are DAs */
  358.         GetItem(GetMHandle(mApple), item, daName);
  359.         OpenDeskAcc(daName);
  360.     }
  361. }
  362.  
  363.     void
  364. DoFileMenu(
  365.     short                    item
  366. ){
  367.     switch(item){
  368.     case iQuit:
  369.         StopMovieTalk();
  370.         
  371.         ExitToShell();
  372.     }
  373. }
  374.  
  375.     void
  376. DoVideoPhoneMenu(
  377.     short                    item
  378. ){
  379.     switch(item){
  380.     case iCall:
  381.         DoMenuCall();
  382.         break;
  383.         
  384.     case iHangUp:
  385.         DoMenuHangUp();
  386.     }
  387. }
  388.  
  389.     void
  390. StopMovieTalk(
  391.     void
  392. ){
  393.     CloseComponent(gCC);
  394.     CloseComponent(gBC);
  395. }
  396.  
  397.     void
  398. DoMenuCall(
  399.     void
  400. ){
  401.     MTNameListPtr            names;
  402.     MTNamePtr                np;
  403.     int                        count;
  404.     
  405.     if(MTBrowserBrowse(gBC, 0, "\pLets go Fishing…", (MTCString)"mtlkatlk\tSeeWorld\x0Dmtlkatlk\tVideoPhone\x0Dmtlkatlk\tMulticaster\x0D", 0, &names) != noErr)
  406.         return;
  407.         
  408.     count = GetMTNameListCount(names);
  409.     np = &(names->list[0]);
  410.  
  411.     while(--count >= 0)
  412.         CallOne(np++);
  413.         
  414.     DisposeMTNameList(names);
  415. }
  416.  
  417.     void
  418. CallOne(
  419.     MTNamePtr                np
  420. ){
  421.     MemberPtr                mp;
  422.     
  423.     if(!(mp = FindMember(0)))
  424.         return;
  425.         
  426.     mp->member = MTConferenceCall(gCC, (MTCString)"See Wiz", np);
  427. }
  428.  
  429.     void
  430. DoMenuHangUp(
  431.     void
  432. ){
  433.     MTConferenceTerminate(gCC, gConference);
  434.     gConference = 0;        // just to suppress menu choice
  435. }
  436.  
  437.     void
  438. DoConferenceEvent(
  439.     MTConferenceEventPtr    ce
  440. ){
  441.     switch(ce->what){
  442.     case mtIncomingCallEvent:
  443.         DoIncomingCall(ce);
  444.         break;
  445.     
  446.     case mtMemberJoiningEvent:
  447.         DoMemberJoining(ce);
  448.         break;
  449.  
  450.     case mtConferenceReadyEvent:
  451.         DoConfReady(ce);
  452.         break;
  453.     
  454.     case mtConferenceTerminatedEvent:
  455.         DoConfTerminated(ce);
  456.         break;
  457.     
  458.     case mtMemberReadyEvent:
  459.         DoMemberReady(ce);
  460.         break;
  461.     
  462.     case mtMemberTerminatedEvent:
  463.         DoMemberTerminated(ce);
  464.         break;
  465.     
  466.     case mtPhoneRingingEvent:
  467.         DoPhoneRinging(ce);
  468.         break;
  469.     
  470.     case mtRefusedEvent:
  471.         Sorry(701, 1, ce->who, ce->err);
  472.         break;
  473.     
  474.     case mtFailedEvent:
  475.         Sorry(701, 2, ce->who, ce->err);
  476.     }
  477.     
  478.     if(ce->surprise)
  479.         DisposeHandle(ce->surprise);
  480. }
  481.  
  482.     void
  483. DoIncomingCall(
  484.     MTConferenceEventPtr    ce
  485. ){
  486.     MemberPtr                mp;
  487.     OSErr                    reason;
  488.     
  489.     reason = 0;
  490.     
  491.     if((ce->bonus & mtSendMediaModeMask) && !(ce->bonus & mtReceiveMediaModeMask))
  492.         reason = mtConnectionRefusedErr;        // no peeking
  493.     else if(mp = FindMember(0))
  494.         mp->member = ce->who;
  495.     else{
  496.         reason = paramErr;
  497.         
  498.         Sorry(702, 1, ce->who, 0);
  499.     }
  500.         
  501.     MTConferenceReply(gCC, ce->who, reason);
  502. }
  503.  
  504.     void
  505. DoMemberJoining(
  506.     MTConferenceEventPtr    ce
  507. ){
  508.     MemberPtr                mp;
  509.     
  510.     if(mp = FindMember(0))
  511.         mp->member = ce->who;
  512.     else
  513.         Sorry(702, 2, ce->who, 0);
  514. }
  515.  
  516.     void
  517. DoConfReady(
  518.     MTConferenceEventPtr    ce
  519. ){
  520.     if(gConference)
  521.         MTConferenceMerge(gCC, gConference, ce->who);
  522.     else{
  523.         MTConferenceActivateConference(gCC, gConference = ce->who, gMember[0].controller);
  524.         
  525.         ShowWindow(gGallery);
  526.     }
  527. }
  528.  
  529.     void
  530. DoMemberReady(
  531.     MTConferenceEventPtr    ce
  532. ){
  533.     MemberPtr                mp;
  534.     MTControllerComponent    mtc;
  535.     
  536.     if(ce->bonus & mtReceiveMediaModeMask){    
  537.         if(!(mp = FindMember(ce->who)))
  538.             return;
  539.     
  540.         mtc = MTConferenceNewPreparedController(gCC, &mp->box, 0, 0);
  541.                
  542.         mp->controller = mtc;
  543.         
  544.         // sets the GWorld    
  545.         MTControllerSetStreamDirector(mtc, MTControllerGetStreamDirector(mtc), gGallery, TOPLEFT(mp->box));
  546.     }else
  547.         mtc = 0;
  548.                        
  549.     MTConferenceActivateMember(gCC, ce->who, mtc);
  550. }
  551.  
  552.     pascal Boolean
  553. GetInOnTheAction(
  554.     MTControllerComponent    mtc,
  555.     MTControllerActionType    action,
  556.     VoidPtr                    params,
  557.     long                    /* unused */
  558. ){
  559.     MemberPtr                mp;
  560.     Rect                    box;
  561.     
  562.     if((action != mtControllerActionControllerSizeChanged) || !(*(BooleanPtr)params))
  563.         return(false);
  564.     
  565.     if(!(mp = FindController(mtc)))
  566.         return(false);
  567.             
  568.     box = mp->box;
  569.     box.bottom += 16;
  570.     
  571.     // sets the Matrix
  572.     MTControllerSetControllerBoundsRect(mtc, &box);
  573.     
  574.     return(false);
  575. }
  576.  
  577.     void
  578. DoMemberTerminated(
  579.     MTConferenceEventPtr    ce
  580. ){
  581.     MemberPtr                mp;
  582.     
  583.     if(!(mp = FindMember(ce->who)))
  584.         return;
  585.         
  586.     if(mp->controller)
  587.         MTConferenceDisposeController(gCC, mp->controller);
  588.         
  589.     mp->controller = 0;
  590.     mp->member = 0;
  591.     
  592.     SetPort(gGallery);
  593.     EraseRect(&mp->box);
  594. }
  595.  
  596.     void
  597. DoConfTerminated(
  598.     MTConferenceEventPtr    ce
  599. ){
  600.     if(gConference == ce->who)
  601.         gConference = 0;
  602.     
  603.     if(!gConference)    
  604.         HideWindow(gGallery);
  605. }
  606.  
  607.     void
  608. DoPhoneRinging(
  609.     MTConferenceEventPtr    ce
  610. ){
  611.     Handle                    ph;
  612.     
  613.     if((ce->bonus & mtRequiredMessagesModeMask) && Requires(ce->who, PW_CLEAR) && (ph = GetPassword((Ptr)MTConferenceGetMemberName(gCC, ce->who))))
  614.         MTConferenceSendMessageToMember(gCC, ce->who, ph, PW_CLEAR, 1);
  615. }
  616.  
  617.     Boolean
  618. Requires(
  619.     MTConferenceMember        who,
  620.     OSType                    type
  621. ){
  622.     MTCapabilitiesHandle    ch;
  623.     MTCapabilitiesPtr        cp;
  624.     int                        n;
  625.     
  626.     ch = MTConferenceGetMemberMessageCapabilities(gCC, who);
  627.     
  628.     for(n = (*ch)->count, cp = (*ch)->capability; --n >= 0; cp++)
  629.         if(type == cp->messageType && cp->desires == mtMessageRequiredCapability){
  630.             DisposeHandle((Handle) ch);
  631.             return(true);
  632.         }
  633.     
  634.     DisposeHandle((Handle) ch);
  635.     return(false);
  636. }
  637.  
  638.     Handle
  639. GetPassword(
  640.     Ptr                        name
  641. ){
  642.     DialogRef                dp;
  643.     short                    itemHit;
  644.     Handle                    ph;
  645.     Str255                    p1;
  646.     
  647.     ParamText(nil, c2pstr(strcpy((char*)p1, name)), nil, nil);
  648.     gPassword[0] = 0;
  649.     
  650.     dp = GetNewDialog(rPassword, 0, (WindowRef) -1);
  651.     SetDialogDefaultItem(dp, diOK);
  652.     SetDialogCancelItem(dp, diCancel);
  653.     SetDialogTracksCursor(dp, true);
  654.     PostEvent(keyDown, '\b');        // ick
  655.     
  656.     do{
  657.         EnableButton(dp, diOK, gPassword[0]);
  658.         
  659.         ModalDialog(0, &itemHit);
  660.         
  661.         GetValue(gPassword, dp, diPassword);
  662.     }while(itemHit > diCancel);
  663.     
  664.     DisposeDialog(dp);
  665.     InitCursor();
  666.     
  667.     if(itemHit == diCancel)
  668.         return(0);
  669.     
  670.     PtrToHand(gPassword, &ph, strlen((char*)gPassword)+1);
  671.     
  672.     return(ph);
  673. }
  674.  
  675.     void
  676. EnableButton(
  677.     DialogRef                dp,
  678.     short                    item,
  679.     Boolean                    enabled
  680. ){
  681.     Handle                    ih;
  682.     Rect                    rect;
  683.     short                    type;
  684.     
  685.     GetDialogItem(dp, item, &type, &ih, &rect);
  686.     
  687.     if(enabled)
  688.         type &= ~itemDisable;
  689.     else
  690.         type |= itemDisable;
  691.         
  692.     HiliteControl((ControlHandle) ih, enabled ? 0 : 255);
  693.     
  694.     SetDialogItem(dp, item, type, ih, &rect);
  695.     
  696.     SetPort(dp);
  697.     InsetRect(&rect, -5, -5);
  698.     InvalRect(&rect);
  699. }
  700.  
  701.     void
  702. GetValue(
  703.     BytePtr                    p,
  704.     DialogRef                dp,
  705.     short                    item
  706. ){
  707.     Handle                    ih;
  708.     Rect                    rect;
  709.     short                    type;
  710.     
  711.     GetDialogItem(dp, item, &type, &ih, &rect);
  712.     GetDialogItemText(ih, p);
  713.     
  714.     if(p[0] && p[p[0]] < ' '){
  715.         p[0]--;            // strip CR or other junk
  716.         SetDialogItemText(ih, p);
  717.     }
  718.     
  719.     p2cstr(p);
  720. }
  721.     
  722.     MemberPtr
  723. FindMember(
  724.     MTConferenceMember        who
  725. ){
  726.     int                        i;
  727.     
  728.     i = (TickCount() % MAXMEMBERS) + 1;
  729.     if(who == gMember[i].member)
  730.         return(&gMember[i]);
  731.     
  732.     for(i = 1; i <= MAXMEMBERS; i++)
  733.         if(who == gMember[i].member)
  734.             return(&gMember[i]);
  735.             
  736.     return(0);
  737. }
  738.     
  739.     MemberPtr
  740. FindController(
  741.     MTControllerComponent    mtc
  742. ){
  743.     int                        i;
  744.     
  745.     for(i = 1; i <= MAXMEMBERS; i++)
  746.         if(mtc == gMember[i].controller)
  747.             return(&gMember[i]);
  748.             
  749.     return(0);
  750. }
  751.  
  752.     void
  753. Sorry(
  754.     int                        why,
  755.     int                        note,
  756.     MTConferenceMember        who,
  757.     OSErr                    err
  758. ){
  759.     Str255                p1, p2, p3;
  760.     
  761.     GetIndString(p1, why, note);
  762.     
  763.     strcpy((char*)p2, (char*)MTConferenceGetMemberName(gCC, who));
  764.     sprintf((char*)p3, "%d", err);
  765.     
  766.     ParamText(nil, p1, c2pstr((char*)p2), c2pstr((char*)p3));
  767.     
  768.     CautionAlert(why, 0);
  769. }